Skip to content

Conversation

dzhidzhoev
Copy link
Member

@dzhidzhoev dzhidzhoev commented Aug 20, 2025

The test llvm/test/DebugInfo/X86/pr12831.ll was added in 4d358b5 to fix the issue with emission of empty DW_TAG_subprogram tags (https://bugs.llvm.org/show_bug.cgi?id=12831).

However, the test output is not checked properly, and it contains:

0x00000206:   DW_TAG_subprogram

0x00000207:   DW_TAG_reference_type
                DW_AT_type      (0x00000169 "class ")

The reason is that the DIE for the definition DISubprogram "writeExpr" is created during the call to getOrCreateSubprogramDIE(declaration of writeExpr). Therefore, when getOrCreateSubprogramDIE(definition of writeExpr) is first called, we get a recursive chain of calls:

getOrCreateSubprogramDIE(definition of writeExpr)
getOrCreateSubprogramDIE(declaration of writeExpr)
...
getOrCreateSubprogramDIE(definition of writeExpr)

The outer call doesn't expect that the DIE for the definition of writeExpr will be created during the creation of declaration DIE. So, another DIE is created for the same subprogram. In this PR, a check is added to fix that.

I'm not sure whether the problem described in https://bugs.llvm.org/show_bug.cgi?id=12831 is still relevant (I wasn't able to reproduce the problem with C++ reproducer from there). But if this test stays in repo, it should be fixed.

This test was added in 4d358b5 to fix the issue with emission of
empty DW_TAG_subprogram tags (https://bugs.llvm.org/show_bug.cgi?id=12831).

However, the test output is not checked properly, and it contains:
```
0x00000206:   DW_TAG_subprogram

0x00000207:   DW_TAG_reference_type
                DW_AT_type      (0x00000169 "class ")
```

The reason is that the DIE for the definition DISubprogram "writeExpr"
is created during the call to `getOrCreateSubprogramDIE(declaration of writeExpr)`.
Therefore, when `getOrCreateSubprogramDIE(definition of writeExpr)` is
first called, we get a recursive chain of calls:
```
getOrCreateSubprogramDIE(definition of writeExpr)
...
getOrCreateSubprogramDIE(declaration of writeExpr)
...
getOrCreateSubprogramDIE(definition of writeExpr)
```

The outer call doesn't expect that the DIE for the definition of
writeExpr will be created during the creation of declaration DIE.
In this PR, a check is added to fix that.

I'm not sure whether the problem described in
https://bugs.llvm.org/show_bug.cgi?id=12831 is still relevant (I wasn't
able to reproduce the problem with C++ reproducer from there).
But if this test stays in repo, it should be fixed.
@llvmbot
Copy link
Member

llvmbot commented Aug 20, 2025

@llvm/pr-subscribers-debuginfo

Author: Vladislav Dzhidzhoev (dzhidzhoev)

Changes

This test was added in 4d358b5 to fix the issue with emission of empty DW_TAG_subprogram tags (https://bugs.llvm.org/show_bug.cgi?id=12831).

However, the test output is not checked properly, and it contains:

0x00000206:   DW_TAG_subprogram

0x00000207:   DW_TAG_reference_type
                DW_AT_type      (0x00000169 "class ")

The reason is that the DIE for the definition DISubprogram "writeExpr" is created during the call to getOrCreateSubprogramDIE(declaration of writeExpr). Therefore, when getOrCreateSubprogramDIE(definition of writeExpr) is first called, we get a recursive chain of calls:

getOrCreateSubprogramDIE(definition of writeExpr)
...
getOrCreateSubprogramDIE(declaration of writeExpr)
...
getOrCreateSubprogramDIE(definition of writeExpr)

The outer call doesn't expect that the DIE for the definition of writeExpr will be created during the creation of declaration DIE. In this PR, a check is added to fix that.

I'm not sure whether the problem described in https://bugs.llvm.org/show_bug.cgi?id=12831 is still relevant (I wasn't able to reproduce the problem with C++ reproducer from there). But if this test stays in repo, it should be fixed.


Full diff: https://github.com/llvm/llvm-project/pull/154636.diff

2 Files Affected:

  • (modified) llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp (+4)
  • (modified) llvm/test/DebugInfo/X86/pr12831.ll (+36-1)
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index b03fac2d22a52..a99e63672b4bb 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -1351,6 +1351,10 @@ DIE *DwarfUnit::getOrCreateSubprogramDIE(const DISubprogram *SP, bool Minimal) {
       ContextDIE = &getUnitDie();
       // Build the decl now to ensure it precedes the definition.
       getOrCreateSubprogramDIE(SPDecl);
+      // Check whether the DIE for SP has already been created after the call
+      // above.
+      if (DIE *SPDie = getDIE(SP))
+        return SPDie;
     }
   }
 
diff --git a/llvm/test/DebugInfo/X86/pr12831.ll b/llvm/test/DebugInfo/X86/pr12831.ll
index 402bc9aa04505..c37c017a52c29 100644
--- a/llvm/test/DebugInfo/X86/pr12831.ll
+++ b/llvm/test/DebugInfo/X86/pr12831.ll
@@ -1,4 +1,39 @@
-; RUN: llc %s -mtriple=x86_64-unknown-linux-gnu -o /dev/null
+; RUN: llc %s -mtriple=x86_64-unknown-linux-gnu -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s
+
+; Check that there are no empty DW_TAG_subprogram tags.
+; CHECK: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT
+; CHECK: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT
+; CHECK: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT
+; CHECK: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT
+; CHECK: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT
+; CHECK: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT
+; CHECK: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT
+; CHECK: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT
+; CHECK: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT
+; CHECK: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT
+; CHECK: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT
+; CHECK: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT
+; CHECK: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT
+; CHECK: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT
+; CHECK: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT
+; CHECK: DW_TAG_subprogram
+; CHECK-NEXT: DW_AT
+; CHECK-NOT: DW_TAG_subprogram
 
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"

@Michael137
Copy link
Member

Michael137 commented Aug 27, 2025

Can you rename the PR/commit title to state what is being fixed. I.e., something like "avoid generating empty DW_TAG_subprogram entries". Also, could you elaborate on how getOrCreateSubprogramDIE(declaration) causes us to call back into getOrCreateSubprogramDIE(definition)? That seems a bit odd. A stacktrace would be handy. Just from looking at the code it wasn't obvious to me

@dzhidzhoev dzhidzhoev changed the title [DwarfDebug] Restore broken test llvm/test/DebugInfo/X86/pr12831.ll [DwarfDebug] Avoid generating extra subprogram entries Aug 27, 2025
@dzhidzhoev dzhidzhoev changed the title [DwarfDebug] Avoid generating extra subprogram entries [DwarfDebug] Avoid generating extra DW_TAG_subprogram entries Aug 27, 2025
@dzhidzhoev
Copy link
Member Author

dzhidzhoev commented Aug 27, 2025

Can you rename the PR/commit title to state what is being fixed. I.e., something like "avoid generating empty DW_TAG_subprogram entries".

Sure!

Also, could you elaborate on how getOrCreateSubprogramDIE(declaration) causes us to call back into getOrCreateSubprogramDIE(definition)? That seems a bit odd. A stacktrace would be handy. Just from looking at the code it wasn't obvious to me

It happens during the creation of a global (static local) variable "__stored_locally" in DwarfDebug::beginModule().
Below is the list of debug info nodes that are traversed before the repeating getOrCreateSubprogramDIE call. I've marked repeating calls with *.

It's not completely clear to me, why we get this particular chain of calls, as the original reproducer for this test is quite confusing. It may be the case that this test is not relevant for Clang-produced code anymore. I've stumbled upon a probem with this test when trying to make a patch allowing two Functions to refer to the same DISubprogram (which was suggested here #142166 (comment)). I've added an assert that ensures that DIEs for the same DISubprogams are not created twice, and such assert gets triggered by this test.

https://reviews.llvm.org/D144007 could also solve the problem (as subprogram DIEs would be instantiated before global variable creation), but I'm not sure it can be merged before https://reviews.llvm.org/D144006 (the latest attempt of merging it was #119001). I can try reverting this fix after https://reviews.llvm.org/D144007 gets merged.

#142166 could also solve the problem, as it would break the link between !26 and !5 (!DICompositeType would be placed directly inside the declaration subprogram), but there is an argument against this patch #142166 (comment).

   !163 = distinct !DIGlobalVariable(name: "__stored_locally", linkageName: "__stored_locally", line: 2, isLocal: true, isDefinition: true, scope: !114, file: !6, type: !131)
   !114 = !DICompositeType(tag: DW_TAG_class_type, name: "_Base_manager", line: 1, size: 8, align: 8, file: !160, elements: !115)
   !115 = !{!116, !113}
   !116 = !DISubprogram(name: "_M_not_empty_function<BPLFunctionWriter::<lambda at BPLFunctionWriter2.ii:20:36> >", linkageName: "_ZN13_Base_manager21_M_not_empty_functionIZN17BPLFunctionWriter9writeExprEvE3$_0EEvRKT_", line: 3, isLocal: false, isDefinition: false, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, scopeLine: 3, file: !6, scope: !114, type: !117, templateParams: !120)
   !120 = !{!121}
   !121 = !DITemplateTypeParameter(name: "_Tp", type: !26)
*  !26 = !DICompositeType(tag: DW_TAG_class_type, line: 20, size: 8, align: 8, file: !160, scope: !5, elements: !27)
*  !5 = distinct !DISubprogram(name: "writeExpr", linkageName: "_ZN17BPLFunctionWriter9writeExprEv", line: 19, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 19, file: !6, scope: null, type: !7, declaration: !103, retainedNodes: !1)
   !103 = !DISubprogram(name: "writeExpr", linkageName: "_ZN17BPLFunctionWriter9writeExprEv", line: 17, isLocal: false, isDefinition: false, virtualIndex: 6, flags: DIFlagPrivate | DIFlagPrototyped, isOptimized: false, scopeLine: 17, file: !6, scope: !10, type: !7)
   !10 = !DICompositeType(tag: DW_TAG_class_type, name: "BPLFunctionWriter", line: 15, size: 64, align: 64, file: !160, elements: !11)
   !11 = !{!12, !103}
   !12 = !DIDerivedType(tag: DW_TAG_member, name: "MW", line: 16, size: 64, align: 64, flags: DIFlagPrivate, file: !160, scope: !10, baseType: !13)
   !13 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, baseType: !14)
   !14 = !DICompositeType(tag: DW_TAG_class_type, name: "BPLModuleWriter", line: 12, size: 8, align: 8, file: !160, elements: !15)
   !15 = !{!16}
   !16 = !DISubprogram(name: "writeIntrinsic", linkageName: "_ZN15BPLModuleWriter14writeIntrinsicE8functionIFvvEE", line: 13, isLocal: false, isDefinition: false, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, scopeLine: 13, file: !6, scope: !14, type: !17)
   !17 = !DISubroutineType(types: !18)
   !18 = !{null, !19, !20}
   !20 = !DICompositeType(tag: DW_TAG_class_type, name: "function<void ()>", line: 6, size: 8, align: 8, file: !160, elements: !21, templateParams: !97)
   !21 = !{!22, !51, !58, !86, !92}
   !22 = !DISubprogram(name: "function<BPLFunctionWriter::<lambda at BPLFunctionWriter2.ii:20:36> >", line: 8, isLocal: false, isDefinition: false, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, scopeLine: 8, file: !6, scope: !20, type: !23, templateParams: !47)
   !47 = !{!48}
   !48 = !DITemplateTypeParameter(name: "_Functor", type: !26)
*  !26 = !DICompositeType(tag: DW_TAG_class_type, line: 20, size: 8, align: 8, file: !160, scope: !5, elements: !27) <<<=== repeating getOrCreateTypeDIE() call
*  !5 = distinct !DISubprogram(name: "writeExpr", linkageName: "_ZN17BPLFunctionWriter9writeExprEv", line: 19, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 19, file: !6, scope: null, type: !7, declaration: !103, retainedNodes: !1) <<<=== repeating getOrCreateSubprogram(definition of writeExpr)

Here's the stacktrace showing the recursive call to getOrCreateSubprogramDIE(definition of writeExpr):

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  * frame #0: 0x00000001015b0e34 llc`llvm::DwarfUnit::getOrCreateSubprogramDIE(this=0x000000014160d5f0, SP=0x0000600002b44e50, Minimal=false) at DwarfUnit.cpp:1343:7 [opt]
    frame #1: 0x00000001015b2b44 llc`llvm::DwarfUnit::getOrCreateTypeDIE(this=0x000000014160d5f0, TyNode=0x0000600002644840) at DwarfUnit.cpp:655:21 [opt]
    frame #2: 0x00000001015b034c llc`llvm::DwarfUnit::constructTemplateTypeParameterDIE(llvm::DIE&, llvm::DITemplateTypeParameter const*) [inlined] llvm::DwarfUnit::addType(this=0x000000014160d5f0, Entity=0x0000000141835668, Ty=<unavailable>, Attribute=DW_AT_type) at DwarfUnit.cpp:704:44 [opt]
    frame #3: 0x00000001015b033c llc`llvm::DwarfUnit::constructTemplateTypeParameterDIE(this=0x000000014160d5f0, Buffer=<unavailable>, TP=0x0000600000b45550) at DwarfUnit.cpp:1239:5 [opt]
    frame #4: 0x00000001015b0210 llc`llvm::DwarfUnit::addTemplateParams(this=0x000000014160d5f0, Buffer=0x0000000141835638, TParams=<unavailable>) at DwarfUnit.cpp:542:7 [opt]
    frame #5: 0x00000001015b6e84 llc`llvm::DwarfUnit::applySubprogramDefinitionAttributes(this=0x000000014160d5f0, SP=0x0000600003740cc0, SPDie=0x0000000141835638, Minimal=<unavailable>) at DwarfUnit.cpp:1402:3 [opt]
    frame #6: 0x00000001015b6290 llc`llvm::DwarfUnit::applySubprogramAttributes(this=0x000000014160d5f0, SP=0x0000600003740cc0, SPDie=0x0000000141835638, SkipSPAttributes=false) at DwarfUnit.cpp:1430:9 [opt]
    frame #7: 0x00000001015b0f28 llc`llvm::DwarfUnit::getOrCreateSubprogramDIE(this=0x000000014160d5f0, SP=0x0000600003740cc0, Minimal=false) at DwarfUnit.cpp:1366:9 [opt]
    frame #8: 0x00000001015b14e8 llc`llvm::DwarfUnit::constructTypeDIE(this=0x000000014160d5f0, Buffer=0x0000000141835578, CTy=0x00006000026447a0) at DwarfUnit.cpp:1069:9 [opt]
    frame #9: 0x00000001015b2544 llc`llvm::DwarfUnit::createTypeDIE(llvm::DIScope const*, llvm::DIE&, llvm::DIType const*) [inlined] _ZZN4llvm9DwarfUnit13createTypeDIEEPKNS_7DIScopeERNS_3DIEEPKNS_6DITypeEENK3$_0clINS_15DICompositeTypeEEEDaPKT_(this=0x000000016fdfd180, Ty=0x00006000026447a0) at DwarfUnit.cpp:605:5 [opt]
    frame #10: 0x00000001015b251c llc`llvm::DwarfUnit::createTypeDIE(this=0x000000014160d5f0, Context=<unavailable>, ContextDIE=<unavailable>, Ty=0x00006000026447a0) at DwarfUnit.cpp:621:5 [opt]
    frame #11: 0x00000001015b3ca4 llc`llvm::DwarfUnit::constructSubprogramArguments(llvm::DIE&, llvm::DITypeRefArray) [inlined] llvm::DwarfUnit::addType(this=0x000000014160d5f0, Entity=0x0000000141835548, Ty=0x00006000026447a0, Attribute=DW_AT_type) at DwarfUnit.cpp:704:44 [opt]
    frame #12: 0x00000001015b3c90 llc`llvm::DwarfUnit::constructSubprogramArguments(this=0x000000014160d5f0, Buffer=0x00000001418353f8, Args=DITypeRefArray @ 0x000000016fdfd1e8) at DwarfUnit.cpp:913:7 [opt]
    frame #13: 0x00000001015b6670 llc`llvm::DwarfUnit::applySubprogramAttributes(this=0x000000014160d5f0, SP=0x0000600002b454d0, SPDie=0x00000001418353f8, SkipSPAttributes=<unavailable>) at DwarfUnit.cpp:1492:13 [opt]
    frame #14: 0x00000001015b0f28 llc`llvm::DwarfUnit::getOrCreateSubprogramDIE(this=0x000000014160d5f0, SP=0x0000600002b454d0, Minimal=false) at DwarfUnit.cpp:1366:9 [opt]
    frame #15: 0x00000001015b14e8 llc`llvm::DwarfUnit::constructTypeDIE(this=0x000000014160d5f0, Buffer=0x00000001418353c8, CTy=0x0000600002644750) at DwarfUnit.cpp:1069:9 [opt]
    frame #16: 0x00000001015b2544 llc`llvm::DwarfUnit::createTypeDIE(llvm::DIScope const*, llvm::DIE&, llvm::DIType const*) [inlined] _ZZN4llvm9DwarfUnit13createTypeDIEEPKNS_7DIScopeERNS_3DIEEPKNS_6DITypeEENK3$_0clINS_15DICompositeTypeEEEDaPKT_(this=0x000000016fdfd460, Ty=0x0000600002644750) at DwarfUnit.cpp:605:5 [opt]
    frame #17: 0x00000001015b251c llc`llvm::DwarfUnit::createTypeDIE(this=0x000000014160d5f0, Context=<unavailable>, ContextDIE=<unavailable>, Ty=0x0000600002644750) at DwarfUnit.cpp:621:5 [opt]
    frame #18: 0x00000001015b36cc llc`llvm::DwarfUnit::constructTypeDIE(llvm::DIE&, llvm::DIDerivedType const*) [inlined] llvm::DwarfUnit::addType(this=0x000000014160d5f0, Entity=0x0000000141835398, Ty=<unavailable>, Attribute=DW_AT_type) at DwarfUnit.cpp:704:44 [opt]
    frame #19: 0x00000001015b36bc llc`llvm::DwarfUnit::constructTypeDIE(this=0x000000014160d5f0, Buffer=0x0000000141835398, DTy=0x0000600002b452d0) at DwarfUnit.cpp:843:5 [opt]
    frame #20: 0x00000001015b2a28 llc`_ZZN4llvm9DwarfUnit13createTypeDIEEPKNS_7DIScopeERNS_3DIEEPKNS_6DITypeEENK3$_0clINS_13DIDerivedTypeEEEDaPKT_(this=<unavailable>, Ty=<unavailable>) at DwarfUnit.cpp:605:5 [opt] [artificial]
    frame #21: 0x00000001015b23f8 llc`llvm::DwarfUnit::createTypeDIE(this=0x000000014160d5f0, Context=0x0000000000000000, ContextDIE=<unavailable>, Ty=0x0000600002b452d0) at DwarfUnit.cpp:633:5 [opt]
    frame #22: 0x00000001015b5530 llc`llvm::DwarfUnit::constructMemberDIE(llvm::DIE&, llvm::DIDerivedType const*) [inlined] llvm::DwarfUnit::addType(this=0x000000014160d5f0, Entity=0x0000000141835350, Ty=<unavailable>, Attribute=DW_AT_type) at DwarfUnit.cpp:704:44 [opt]
    frame #23: 0x00000001015b5520 llc`llvm::DwarfUnit::constructMemberDIE(this=0x000000014160d5f0, Buffer=<unavailable>, DT=0x0000600002b451d0) at DwarfUnit.cpp:1862:5 [opt]
    frame #24: 0x00000001015b1908 llc`llvm::DwarfUnit::constructTypeDIE(this=0x000000014160d5f0, Buffer=0x0000000141835320, CTy=0x0000600002644700) at DwarfUnit.cpp:1096:11 [opt]
    frame #25: 0x00000001015b2544 llc`llvm::DwarfUnit::createTypeDIE(llvm::DIScope const*, llvm::DIE&, llvm::DIType const*) [inlined] _ZZN4llvm9DwarfUnit13createTypeDIEEPKNS_7DIScopeERNS_3DIEEPKNS_6DITypeEENK3$_0clINS_15DICompositeTypeEEEDaPKT_(this=0x000000016fdfd7c0, Ty=0x0000600002644700) at DwarfUnit.cpp:605:5 [opt]
    frame #26: 0x00000001015b251c llc`llvm::DwarfUnit::createTypeDIE(this=0x000000014160d5f0, Context=<unavailable>, ContextDIE=<unavailable>, Ty=0x0000600002644700) at DwarfUnit.cpp:621:5 [opt]
    frame #27: 0x00000001015b0e5c llc`llvm::DwarfUnit::getOrCreateSubprogramDIE(this=0x000000014160d5f0, SP=0x0000600002b45a50, Minimal=false) at DwarfUnit.cpp:1343:33 [opt]
    frame #28: 0x00000001015b0ed4 llc`llvm::DwarfUnit::getOrCreateSubprogramDIE(this=0x000000014160d5f0, SP=0x0000600002b44e50, Minimal=false) at DwarfUnit.cpp:1353:7 [opt]
    frame #29: 0x00000001015b2b44 llc`llvm::DwarfUnit::getOrCreateTypeDIE(this=0x000000014160d5f0, TyNode=0x0000600002644840) at DwarfUnit.cpp:655:21 [opt]
    frame #30: 0x00000001015b034c llc`llvm::DwarfUnit::constructTemplateTypeParameterDIE(llvm::DIE&, llvm::DITemplateTypeParameter const*) [inlined] llvm::DwarfUnit::addType(this=0x000000014160d5f0, Entity=0x00000001418352f0, Ty=<unavailable>, Attribute=DW_AT_type) at DwarfUnit.cpp:704:44 [opt]
    frame #31: 0x00000001015b033c llc`llvm::DwarfUnit::constructTemplateTypeParameterDIE(this=0x000000014160d5f0, Buffer=<unavailable>, TP=0x0000600000b46330) at DwarfUnit.cpp:1239:5 [opt]
    frame #32: 0x00000001015b0210 llc`llvm::DwarfUnit::addTemplateParams(this=0x000000014160d5f0, Buffer=0x00000001418352c0, TParams=<unavailable>) at DwarfUnit.cpp:542:7 [opt]
    frame #33: 0x00000001015b6e84 llc`llvm::DwarfUnit::applySubprogramDefinitionAttributes(this=0x000000014160d5f0, SP=0x00006000037411d0, SPDie=0x00000001418352c0, Minimal=<unavailable>) at DwarfUnit.cpp:1402:3 [opt]
    frame #34: 0x00000001015b6290 llc`llvm::DwarfUnit::applySubprogramAttributes(this=0x000000014160d5f0, SP=0x00006000037411d0, SPDie=0x00000001418352c0, SkipSPAttributes=false) at DwarfUnit.cpp:1430:9 [opt]
    frame #35: 0x00000001015b0f28 llc`llvm::DwarfUnit::getOrCreateSubprogramDIE(this=0x000000014160d5f0, SP=0x00006000037411d0, Minimal=false) at DwarfUnit.cpp:1366:9 [opt]
    frame #36: 0x00000001015b14e8 llc`llvm::DwarfUnit::constructTypeDIE(this=0x000000014160d5f0, Buffer=0x0000000141835290, CTy=0x00006000026448e0) at DwarfUnit.cpp:1069:9 [opt]
    frame #37: 0x00000001015b2544 llc`llvm::DwarfUnit::createTypeDIE(llvm::DIScope const*, llvm::DIE&, llvm::DIType const*) [inlined] _ZZN4llvm9DwarfUnit13createTypeDIEEPKNS_7DIScopeERNS_3DIEEPKNS_6DITypeEENK3$_0clINS_15DICompositeTypeEEEDaPKT_(this=0x000000016fdfdb90, Ty=0x00006000026448e0) at DwarfUnit.cpp:605:5 [opt]
    frame #38: 0x00000001015b251c llc`llvm::DwarfUnit::createTypeDIE(this=0x000000014160d5f0, Context=<unavailable>, ContextDIE=<unavailable>, Ty=0x00006000026448e0) at DwarfUnit.cpp:621:5 [opt]
    frame #39: 0x000000010157c0a4 llc`llvm::DwarfCompileUnit::getOrCreateGlobalVariableDIE(this=0x000000014160d5f0, GV=0x0000600002e40918, GlobalExprs=<unavailable>) at DwarfCompileUnit.cpp:191:7 [opt]
    frame #40: 0x0000000101589f60 llc`llvm::DwarfDebug::beginModule(this=<unavailable>, M=<unavailable>) at DwarfDebug.cpp:1231:12 [opt]
    frame #41: 0x0000000101554738 llc`llvm::AsmPrinter::doInitialization(this=0x000000014160cff0, M=0x00000001416048a0) at AsmPrinter.cpp:647:14 [opt]
    frame #42: 0x0000000102fb4d88 llc`llvm::FPPassManager::doInitialization(this=0x0000000141607380, M=0x00000001416048a0) at LegacyPassManager.cpp:1453:41 [opt]
    frame #43: 0x0000000102fafdb8 llc`llvm::legacy::PassManagerImpl::run(llvm::Module&) [inlined] (anonymous namespace)::MPPassManager::runOnModule(this=0x0000000141606f90, M=0x00000001416048a0) at LegacyPassManager.cpp:1487:41 [opt]
    frame #44: 0x0000000102fafd18 llc`llvm::legacy::PassManagerImpl::run(this=<unavailable>, M=0x00000001416048a0) at LegacyPassManager.cpp:531:44 [opt]
    frame #45: 0x0000000100003e30 llc`main [inlined] compileModule(argv=<unavailable>, Context=0x000000016fdfe010) at llc.cpp:759:8 [opt]
    frame #46: 0x00000001000026f4 llc`main(argc=<unavailable>, argv=<unavailable>) at llc.cpp:404:22 [opt]
    frame #47: 0x000000018d306b98 dyld`start + 6076

Copy link
Member

@jmorse jmorse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense / I think I understand it, we can end up committing to creating a DIE in getOrCreateSubprogramDIE, but then create ourselves between committing and actually creating the DIE. I've seen these random-nameless-entryless DW_TAG_subprograms in many files, fixing this is most welcome.

IMO the comment added to DwarfUnit.cpp should signal that it's a workaround, to encourage someone in the future to either fix it, or not get in their way if they're fixing it. Ideally the test would be more focused, but it's pre-existing, after all.

@dzhidzhoev
Copy link
Member Author

Thank you!
I've added a FIXME comment.

@Michael137, please let me know if you have concerns. Otherwise, I'll merge it.

@dzhidzhoev dzhidzhoev merged commit 8c1e62b into llvm:main Aug 29, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants